#region license
# This file is part of Grawlix.
# 
# Grawlix is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
# 
# Grawlix is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public
# License along with Grawlix.  If not, see
# <http://www.gnu.org/licenses/>.
#endregion

"""Domain provision with specially mapped domain types."""

namespace Grawlix.Services
import C5
import System

final transient class MappedDomainProvider(ServiceBase, IDomainProvider):
"""A domain provider based on a defined mapping."""
	
	def constructor(
		[required] mapping as IDictionary[of string, IDomainFactory],
		[required] fallback as IDomainFactory):
	"""
	Initializes the mapping of names to specific factories.
	Param mapping: The defined mapping.
	Param fallback: The factory to use for unrecognized names.
	"""
		for pair in mapping:
			_mapping[pair.Key.ToLowerInvariant()] = pair.Value
		_fallback = fallback
	
	[lock(_domainMap)]
	def Find([required] name as string, [required] game as Game):
	"""
	Look up a domain by name, loading if needed.
	Param game: The game to create the domain in.
	Param name: The name of the domain to access.
	Returns: The domain, which may not yet be loaded.
	"""
		lowerName = name.ToLowerInvariant()
		if _domainMap.Contains(lowerName):
			return _domainMap[lowerName].Target
		if _mapping.Contains(lowerName):
			factory = _mapping[lowerName]
		else:
			factory = _fallback
		domain = factory.Create(name, game)
		_domainMap[lowerName] = domain
		domain.Target.Activate()
		return domain.Target
	
	override def ToString():
	"""
	Get a string representation for this object.
	Returns: A string representation for this object.
	"""
		return "MappedDomainProvider ${_mapping} fallback=${_fallback}"
	
	Domains:
	"""A set of the active map domains."""
		[lock(_domainMap)]
		get:
			proxies = _domainMap.Values
			domains = C5.ArrayList[of Domain](proxies.Count)
			for proxy in proxies:
				domains.Add(proxy.Target)
			return domains
	
	private _domainMap = \
		HashDictionary[of string, ExternalProxy[of Domain]]()
	"""The internal table of all map domains."""
	
	private _mapping = HashDictionary[of string, IDomainFactory]()
	"""The mapping of special Domains by factory."""
	
	private _fallback as IDomainFactory
	"""The fallback factory to process unset names."""
